﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Marmat.Forms
{
    public class FileIconAPI
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        }

        [DllImport("shell32.dll", EntryPoint = "SHGetFileInfo")]
        public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttribute, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint Flags);
        [DllImport("User32.dll", EntryPoint = "DestroyIcon")]
        public static extern int DestroyIcon(IntPtr hIcon);
        [DllImport("shell32.dll")]
        public static extern uint ExtractIconEx(string lpszFile, int nIconIndex, int[] phiconLarge, int[] phiconSmall, uint nIcons);

        /// <summary>
        /// 获取文件的图标
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static Icon GetIcon(string fileName)
        {
            var info = new System.IO.FileInfo(fileName);
            if (System.IO.File.Exists(fileName) == false)
            {
                string directory = System.IO.Path.Combine(Application.LocalUserAppDataPath, "Icon");
                if (System.IO.Directory.Exists(directory) == false)
                {
                    System.IO.Directory.CreateDirectory(directory);
                }

                fileName = System.IO.Path.Combine(directory, "Icon" + info.Extension);
                if (System.IO.File.Exists(fileName) == false)
                {
                    System.IO.File.WriteAllText(fileName, "");
                }
            }

            if (info.Extension == ".exe" || Icons.ContainsKey(info.Extension) == false)
            {
                var shfi = new SHFILEINFO();
                SHGetFileInfo(fileName, 0x80U, ref shfi, (uint)Marshal.SizeOf(shfi), 0x100 | 0x400);
                // 获取文件夹的图标及类型
                if (info.Extension == ".exe")
                {
                    Icon icn = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
                    // 销毁图标
                    DestroyIcon(shfi.hIcon);
                    return icn;
                }

                Icons.Add(info.Extension, (Icon)Icon.FromHandle(shfi.hIcon).Clone());
                // 销毁图标
                DestroyIcon(shfi.hIcon);
            }

            return (Icon)Icons[info.Extension].Clone();
        }

        private static Dictionary<string, Icon> Icons
        {
            get
            {
                if (m_Icons is null)
                {
                    m_Icons = new Dictionary<string, Icon>();
                }

                return m_Icons;
            }
        }

        private static Dictionary<string, Icon> m_Icons;
    }
}